////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxncsservice.h
/// @brief CamX Non-Camera Service Class Implementation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXNCSSERVICE_H
#define CAMXNCSSERVICE_H

#include "camxdefs.h"
#include "camxncsintf.h"
#include "camxncssensor.h"
#include "camxchicontext.h"

CAMX_NAMESPACE_BEGIN

const UINT MaxSensorInterfaceObjects = 5;   ///< Max Sensor interface objects.
const UINT NCSServiceTimeout         = 100; ///< Service timeout period
const UINT NCSServiceMaxJobs         = 30;  ///< NCS max jobs

struct NCSServiceHandle
{
    INCSIntfBase*   pNCSIntfObject[MaxSensorInterfaceObjects];  ///< Array of NCS interface objects
    NCSIntfState    intfStates[MaxSensorInterfaceObjects];      ///< Array of NCS interface objects' states
    NCSIntfType     intfType;                                   ///< NCS Interface type
    NCSSensor*      pSensorClients[MaxSupportedSensorClients];  ///< NCS Sensor clients
    UINT            numActiveClients;                           ///< Num active clients
    BOOL            isSessionCreated;                           ///< Session created flag
};

struct NCSThreadContext
{
    JobHandle                   hJobHandle;       ///< Job family handle
    ThreadManager*              pThreadManager;   ///< Thread manager pointer
    LightweightDoublyLinkedList NCSJobQueue;      ///< NCS Job queue
    Mutex*                      pNCSQMutex;       ///< NCS Queue mutex variable
    Condition*                  pNCSQCondVar;     ///< NCS Queue condition variable
    Mutex*                      pNCSStateMutex;   ///< NCS Queue mutex variable
    Condition*                  pNCSStateCondVar; ///< NCS Queue condition variable
    BOOL                        isRunning;        ///< Flag to indicate if NCS thread is running
    BOOL                        flushDone;        ///< Flag indicating if flush is done
    VOID*                       pServiceObject;   ///< NCS Service object
};

enum JobType
{
    NCSFlushCmdType = 0,      ///< NCS start thread.
    NCSRequestProcType        ///< NCS Process Request
};

struct NCSJob
{
    JobType jobType;  ///< Job Type
    VOID*   pPayload; ///< Pointer to the payload data.
};

struct NCSThreadData
{
    NCSThreadContext* pThreadContext; ///< Pointer to the thread context.
    NCSJob*           pJob;           ///< Pointer to the payload data.
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements the NCS Service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOWHINE CP044: Need to set visibility, false positive
class NCSService
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// NCSService
    ///
    /// @brief  the default constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC NCSService() = default;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///  ~NCSService
    ///
    /// @brief  the destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC ~NCSService();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  Initialize the NCS service
    ///
    /// @param  pChiContext pointer to the chi context
    ///
    /// @return CamxResultSuccess in case of successfull execution
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC CamxResult Initialize(
        ChiContext* pChiContext);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// QueryCapabilites
    ///
    /// @brief  Query the capabilities of a sensor type
    ///
    /// @param  pCaps      Capabilities pointer to be filled
    /// @param  sensorType Sensor type
    ///
    /// @return CamxResultSuccess in case of successfull execution
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC CamxResult QueryCapabilites(
        NCSSensorCaps* pCaps,
        NCSSensorType sensorType);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CreateClientSession
    ///
    /// @brief  Create a session for the clients
    ///
    /// @param  pSensor Sensor object pointer
    ///
    /// @return CamxResultSuccess in case of successfull execution
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC CamxResult CreateClientSession(
        VOID* pSensor);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RegisterService
    ///
    /// @brief  API for a client to register a service
    ///
    /// @param  sensorType    sensor type
    /// @param  pConfigParams Config params
    ///
    /// @return NCS sensor object handle
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC NCSSensor* RegisterService(
        NCSSensorType sensorType,
        VOID* pConfigParams);


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UnregisterService
    ///
    /// @brief  Unregister the NCS sensor object
    ///
    /// @param  phNCSSensorHandle NCS Sensor handle
    ///
    /// @return CamxResultSuccess in case of successfull execution
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC CamxResult UnregisterService(
        NCSSensor* phNCSSensorHandle);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReleaseSession
    ///
    /// @brief  Release the session
    ///
    /// @return CamxResultSuccess in case of successful execution
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_VISIBILITY_PUBLIC CamxResult ReleaseSession();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EnqueueJob
    ///
    /// @brief  Enquque a job to the NCS thread
    ///
    /// @param  pJob Pointer to the job payload
    ///
    /// @return CamxResultSuccess if enqueue successfull
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult EnqueueJob(
        NCSJob* pJob);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// NCSServicePollThread
    ///
    /// @brief  NCS polling thread for inputs from QSEE sensors, service
    ///
    /// @param  pPayload Pointer to the payload
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID* NCSServicePollThread(
        VOID* pPayload);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessPendingJobs
    ///
    /// @brief  Process NCS Service jobs
    ///
    /// @param  pThreadContext NCS thread context
    ///
    /// @return CamxResultSuccess if processing successfull
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ProcessPendingJobs(
        NCSThreadContext* pThreadContext);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateIntfStates
    ///
    /// @brief  Process NCS Service jobs
    ///
    /// @param  pThreadContext NCS thread context
    ///
    /// @return CamxResultSuccess if update successfull
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult UpdateIntfStates(
        NCSThreadContext* pThreadContext);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// HandleError
    ///
    /// @brief  Process NCS Service error
    ///
    /// @param  pThreadContext NCS thread context
    ///
    /// @return CamxResultSuccess if handling successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult HandleError(
        NCSThreadContext* pThreadContext);

    NCSServiceHandle m_hNCSServiceContext; ///< NCS Service context member variable

private:
    NCSService(const NCSService&)            = delete;  ///< Disallow the copy constructor.
    NCSService& operator=(const NCSService&) = delete;  ///< Disallow assignment operator
    NCSThreadContext m_hNCSPollThHandle;                 ///< NCS thread realted data handle

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// StartNCSService
    ///
    /// @brief  Start NCS Service thread
    ///
    /// @return CamxResultSuccess if started successfully
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult StartNCSService();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// StopNCSService
    ///
    /// @brief  Stop NCS Service thread
    ///
    /// @return CamxResultSuccess if started successfully
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult StopNCSService();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FlushNCSService
    ///
    /// @brief  Flush NCS Service jobs
    ///
    /// @return CamxResultSuccess if flush successfull
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult FlushNCSService();

};

CAMX_NAMESPACE_END

#endif // CAMXNCSSERVICE_H
